package com.shxy.service.impl;

import com.shxy.dao.MajorInServiceDao;
import com.shxy.dao.base.*;
import com.shxy.entity.base.*;
import com.shxy.entity.custom.CustomClazz;
import com.shxy.entity.custom.CustomStudent;
import com.shxy.entity.custom.MajorInService;
import com.shxy.service.IBaseInfoService;
import lombok.extern.java.Log;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Log
public class BaseInfoService implements IBaseInfoService {
    @Autowired private StudentDao studentDao;
    @Autowired private CollegeDao collegeDao;
    @Autowired private MajorDao majorDao;
    @Autowired private ClazzDao clazzDao;
    @Autowired private StuRawDao stuRawDao;
    @Autowired private MajorInServiceDao majorInServiceDao;

    @Override
    public List<StuRaw> getStuRawAll() {
        return stuRawDao.findAll();
    }

    @Override
    public Optional<College> addCollege(String name) {
        Optional<College> college = collegeDao.findFirstByName(name);
        if(college.isEmpty()){
            College clg = new College();
            clg.setName(name);
            collegeDao.save(clg);
            college = Optional.of(clg);
        }
        return college;
    }

    @Override
    public Optional<Major> addMajor(String name) {
        Optional<Major> major = majorDao.findFirstByName(name);
        if(major.isEmpty()) {
            Major m = new Major();
            m.setName(name);
            major = Optional.of(majorDao.save(m));
        }
        return major;
    }

    @Override
    public Optional<MajorInService> addMajorInService(String grade, College college, Major major) {
        Optional<MajorInService> mis = majorInServiceDao.findByYearAndMajor(grade, major);
        if(mis.isEmpty()) {
            MajorInService m = new MajorInService();
            m.setCollege(college);
            m.setMajor(major);
            m.setYear(grade);
            mis = Optional.of(majorInServiceDao.save(m));
        }
        return mis;
    }

    @Override
    public Optional<CustomClazz> addClazz(College college, Major major, String clazzName, String year) {
        // 1、根据学年和班级名称查询班级，如果存在，则直接返回
        Optional<CustomClazz> clazz = clazzDao.findFirstByNameAndYear(clazzName, year);
        if(clazz.isPresent()) {
            return clazz;
        }

        // 2、根据学年和专业查询运行的专业信息
        Optional<MajorInService> mis = majorInServiceDao.findByYearAndMajor(year, major);
        // 3、如果班级不存在但该专业存在，则创建并添加班级
        if(mis.isPresent()) {
            CustomClazz clz = new CustomClazz();
            clz.setMajorInService(mis.get());
            clz.setName(clazzName);
            clz.setYear(year);
            clazz = Optional.of(clazzDao.save(clz));
        }
        // 4、返回创建后的班级
        return clazz;
    }

    @Override
    public List<CustomClazz> initClazzs() {
        // 1、获取全部学生信息
        List<StuRaw> stus = getStuRawAll();
        // 2、根据班级过滤出学生信息
        TreeSet<StuRaw> stuRaws = new TreeSet<>((s1, s2) -> s1.getClazz().trim().compareTo(s2.getClazz().trim()));
        stuRaws.addAll(stus);
        ArrayList<StuRaw> stuList = new ArrayList<>(stuRaws);

        ArrayList<CustomClazz> clazzs = new ArrayList<>();
        // 3、循环保存班级信息
        for (StuRaw s: stuList) {
            Optional<College> college = addCollege(s.getDept().trim());
            Optional<Major> major = addMajor(s.getMajor().trim());
            Optional<CustomClazz> clazz = addClazz(college.get(), major.get(), s.getClazz().trim(), s.getGrade().trim());

            if(clazz.isPresent()) {
                clazzs.add(clazz.get());
            }
        }

        // 4、保存班级列表
        clazzDao.saveAll(clazzs);

        return clazzs;
    }

    @Override
    public List<CustomStudent> initStudents() {
        // 1、获取全部需要导入的学生信息
        List<StuRaw> stuRaws = getStuRawAll();

        // 2、构建学生列表
        ArrayList<CustomStudent> stus = new ArrayList<>();
        for (StuRaw s: stuRaws) {
            // 4、根据学号查找学生
            Optional<CustomStudent> ss = studentDao.findByCode(s.getCode());
            // 5、如果学生不存在
            if(ss.isEmpty()){
                // 6、查找对应的班级
                Optional<CustomClazz> clazz = clazzDao.findFirstByNameAndYear(s.getClazz().trim(), s.getGrade().trim());
                // 7、如果班级存在，则创建学生并添加到列表
                if(clazz.isPresent()) {
                    CustomStudent stu = new CustomStudent();
                    BeanUtils.copyProperties(s, stu);
                    stu.setClazz(clazz.get());
                    stus.add(stu);
                }
            }
        }

        // 8、保存学生列表
        studentDao.saveAll(stus);

        return stus;
    }


    @Override
    public MajorInService saveMajorInService(MajorInService majorInService) {
        return majorInServiceDao.save(majorInService);
    }

    @Override
    public CustomClazz saveClazz(CustomClazz clazz) {
        return clazzDao.save(clazz);
    }

    @Override
    public List<String> getYearsAll() {
        return clazzDao.findAll().stream().map(CustomClazz::getYear)
                .distinct()
                .collect(Collectors.toList());
    }

    @Override
    public List<College> getCollegesAll(String year) {
        return clazzDao.findAll().stream()
                .filter(clazz -> clazz.getYear().equals(year))
                .map(CustomClazz::getCollege)
                .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(College::getId))), ArrayList::new));
    }

    @Override
    public List<Major> getMajors(String year, int collegeId) {
        return clazzDao.findAll().stream()
                .filter(clazz -> clazz.getYear().equals(year) && (collegeId == 0 ? true : clazz.getCollege().getId() == collegeId))
                .map(CustomClazz::getMajor)
                .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Major::getId))), ArrayList::new));
    }

    @Override
    public List<CustomClazz> getClazzList(String year, int collegeId, int majorId) {
        return clazzDao.findAll().stream()
                .filter(clazz -> clazz.getYear().equals(year) && ((majorId == 0 ? true : clazz.getMajor().getId() == majorId) && (collegeId == 0 ? true : clazz.getCollege().getId() == collegeId)))
                .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(CustomClazz::getId))), ArrayList::new));
    }
}
